"""
Pytest configuration and fixtures for backend tests
"""

import pytest
import asyncio
from typing import AsyncGenerator, Generator
from httpx import AsyncClient, ASGITransport
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import StaticPool

# Import from the correct path
import sys
import os

# Add backend directory to Python path
backend_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
if backend_path not in sys.path:
    sys.path.insert(0, backend_path)

# Set test environment variables
os.environ["SECRET_KEY"] = "test-secret-key-for-testing-only"
os.environ["ENVIRONMENT"] = "testing"
os.environ["DEBUG"] = "true"

from main import app
from app.core.database import get_business_db, get_extractor_db
from app.core.config import settings


# Test database URLs
TEST_BUSINESS_DB_URL = "sqlite+aiosqlite:///:memory:"
TEST_EXTRACTOR_DB_URL = "sqlite+aiosqlite:///:memory:"


@pytest.fixture(scope="session")
def event_loop() -> Generator:
    """Create an instance of the default event loop for the test session."""
    loop = asyncio.get_event_loop_policy().new_event_loop()
    yield loop
    loop.close()


@pytest.fixture
async def test_business_engine():
    """Create test business database engine"""
    engine = create_async_engine(
        TEST_BUSINESS_DB_URL,
        echo=False,
        poolclass=StaticPool,
        connect_args={
            "check_same_thread": False,
        },
    )

    # Create all tables
    from app.models.business import Base
    async with engine.begin() as conn:
        await conn.run_sync(Base.metadata.create_all)

    yield engine

    await engine.dispose()


@pytest.fixture
async def test_extractor_engine():
    """Create test extractor database engine"""
    engine = create_async_engine(
        TEST_EXTRACTOR_DB_URL,
        echo=False,
        poolclass=StaticPool,
        connect_args={
            "check_same_thread": False,
        },
    )

    # Create all tables
    from app.models.extractor import Base
    async with engine.begin() as conn:
        await conn.run_sync(Base.metadata.create_all)

    yield engine

    await engine.dispose()


@pytest.fixture
async def test_business_db(test_business_engine) -> AsyncGenerator[AsyncSession, None]:
    """Create test business database session"""
    async_session = sessionmaker(
        test_business_engine, class_=AsyncSession, expire_on_commit=False
    )

    async with async_session() as session:
        yield session


@pytest.fixture
async def test_extractor_db(test_extractor_engine) -> AsyncGenerator[AsyncSession, None]:
    """Create test extractor database session"""
    async_session = sessionmaker(
        test_extractor_engine, class_=AsyncSession, expire_on_commit=False
    )

    async with async_session() as session:
        yield session


@pytest.fixture
def override_database_dependencies(test_business_db, test_extractor_db):
    """Override database dependencies for testing"""
    app.dependency_overrides[get_business_db] = lambda: test_business_db
    app.dependency_overrides[get_extractor_db] = lambda: test_extractor_db

    yield

    app.dependency_overrides.clear()


@pytest.fixture
async def client(override_database_dependencies) -> AsyncGenerator[AsyncClient, None]:
    """Create test client"""
    transport = ASGITransport(app=app)
    async with AsyncClient(transport=transport, base_url="http://test") as ac:
        yield ac


@pytest.fixture
def mock_user():
    """Mock user for authentication tests"""
    return {
        "user_id": "test-user-123",
        "email": "test@example.com",
        "name": "Test User"
    }


@pytest.fixture
def auth_headers(mock_user):
    """Create mock authorization headers"""
    from app.core.security import create_access_token
    token = create_access_token(data={"sub": mock_user["user_id"]})
    return {"Authorization": f"Bearer {token}"}


@pytest.fixture
async def sample_team(test_business_db):
    """Create a sample team for testing"""
    from app.models.business import Team
    import uuid

    team = Team(
        id=str(uuid.uuid4()),
        name="Test Team",
        description="A test team for unit testing",
        created_by="test-user-123"
    )

    test_business_db.add(team)
    await test_business_db.commit()
    await test_business_db.refresh(team)

    return team


@pytest.fixture
async def sample_metric(test_extractor_db):
    """Create a sample metric for testing"""
    from app.models.extractor import Metric

    metric = Metric(
        name="TestMetric",
        type="histogram",
        component="TestComponent",
        file_path="/test/path/test.xml",
        line_number=42,
        description="Test metric for unit testing",
        units="ms"
    )

    test_extractor_db.add(metric)
    await test_extractor_db.commit()
    await test_extractor_db.refresh(metric)

    return metric


@pytest.fixture
def sample_telemetry_data():
    """Sample telemetry data for API testing"""
    return {
        "id": 1,
        "name": "SampleMetric",
        "type": "histogram",
        "description": "Sample telemetry metric",
        "units": "ms",
        "component": "SampleComponent",
        "file_path": "/sample/path/sample.xml",
        "line_number": 100,
        "owner": "sample@owner.com",
        "analysis_status": "NOT_ANALYZED",
        "metadata": {}
    }


@pytest.fixture
def sample_team_data():
    """Sample team data for API testing"""
    return {
        "id": "test-team-123",
        "name": "Sample Team",
        "description": "A sample team for testing",
        "created_by": "test-user-123",
        "member_count": 1,
        "assignment_count": 5
    }


@pytest.fixture
def sample_search_query():
    """Sample search query for API testing"""
    return {
        "query": "test metric",
        "filters": {
            "type": ["histogram"],
            "component": ["TestComponent"]
        },
        "include_ukm": True,
        "include_uma": True,
        "include_enums": True
    }


# Test configuration
@pytest.fixture
def test_config():
    """Test configuration settings"""
    return {
        "TEST_MODE": True,
        "ENVIRONMENT": "testing",
        "SECRET_KEY": "test-secret-key",
        "ALGORITHM": "HS256",
        "ACCESS_TOKEN_EXPIRE_MINUTES": 30
    }